package com.dynamic.datasource.factory;

import com.dynamic.datasource.property.DataSourceProperty;
import com.dynamic.datasource.property.GlobalDataSourceProperty;
import com.p6spy.engine.spy.P6DataSource;
import io.seata.rm.datasource.DataSourceProxy;
import io.seata.rm.datasource.xa.DataSourceProxyXA;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author 王先堂
 * @Description 抽象工厂
 * @createTime 2022/03/24/ 10:37:00
 */
@Slf4j
public abstract class AbstractDataSourceFactory implements DataSourceFactory {


    @Resource
    protected GlobalDataSourceProperty globalDataSourceProperty;

    /**
     * 具体的线程池去实现
     *
     * @param dataSourceProperty 配置属性
     * @return
     */
    public abstract DataSource doCreate(DataSourceProperty dataSourceProperty);

    @Override
    public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
        Boolean lazy = dataSourceProperty.getLazy();
        if (lazy == null) {
            lazy = globalDataSourceProperty.getLazy();
            dataSourceProperty.setLazy(lazy);
        }
        //todo 事件触发
        DataSource dataSource = doCreate(dataSourceProperty);
        //todo 初始脚本
        return wrapDataSource(dataSource, dataSourceProperty);
    }

    /**
     * 包装数据源
     *
     * @param dataSource 数据源
     * @param property   配置属性
     * @return 包装后的数据源
     */
    private DataSource wrapDataSource(DataSource dataSource, DataSourceProperty property) {
        String name = property.getName();
        DataSource targetDataSource = dataSource;
        Boolean enableP6spy = globalDataSourceProperty.getP6spy() && property.getP6spy();
        Boolean enbaleSeata = globalDataSourceProperty.getSeata();
        if (enableP6spy) {
            targetDataSource = new P6DataSource(dataSource);
            log.debug("DataSource [{}] wrap p6spy plugin", name);
        }
        String seata = property.getSeata();
        if (enbaleSeata && !StringUtils.isEmpty(seata)) {
            if (seata.equals("XA")) {
                targetDataSource = new DataSourceProxyXA(targetDataSource);
            } else {
                targetDataSource = new DataSourceProxy(targetDataSource);
            }
            log.debug("DataSource [{}] wrap seata plugin transaction mode ", name);
        }
        return new WrapDataSource(name, dataSource, targetDataSource, seata, enableP6spy);

    }
}
